Skip to main content

Overview

OpenCLIP provides advanced distributed training techniques that enable efficient training on hundreds or thousands of GPUs. This guide covers memory-efficient distributed loss computation, gradient accumulation, mixed precision training, and performance optimizations.

Memory-Efficient Distributed Loss

The standard CLIP contrastive loss requires computing a logit matrix of size (batch_size × num_gpus) × (batch_size × num_gpus), leading to O(n²) memory complexity. For large-scale training, this becomes a bottleneck.

The Problem: O(n²) Memory Complexity

Without optimization:
This scales poorly and limits the number of GPUs you can use.

The Solution: Local Loss with Gradient Gathering

OpenCLIP implements an efficient distributed loss computation that achieves O(n) memory complexity while maintaining identical numerical results.
With optimization:

How It Works

  1. --local-loss: Compute loss locally with gathered features, avoiding full global logit matrix
  2. --gather-with-grad: Enable gradient flow through the feature gathering operation
Together, these flags enable linear memory scaling:
Always use --local-loss and --gather-with-grad together for multi-node training (8+ GPUs). These flags are essential for scaling beyond small clusters.

Gradient Accumulation

Gradient accumulation simulates larger batch sizes by accumulating gradients over multiple forward passes before updating weights.

Basic Usage

Effective batch size:

When to Use Gradient Accumulation

Use --accum-freq when:
  1. ✅ You need larger effective batch sizes than GPU memory allows
  2. ✅ You want to maintain a specific batch size across different hardware
  3. ✅ You’re experimenting with very large batch sizes (>100k)
However, try these first:
  1. Enable --precision amp (mixed precision)
  2. Use --grad-checkpointing (memory-compute tradeoff)
  3. Use --local-loss --gather-with-grad (for distributed training)

Performance Implications

Speed: Samples/sec remains approximately constant
  • Without accumulation: Process 1024 samples in 1 step
  • With --accum-freq 4: Process 256 samples × 4 in 4 steps
  • Net throughput: Similar
Memory: Additional GPU memory required for:
  • Cached features from all accumulated batches
  • Multiple loss computations (one per accumulated batch)

Real-World Example

Implementation Details

Gradient accumulation in OpenCLIP:
  1. First N-1 steps: Forward pass with torch.no_grad(), cache features
  2. Nth step: Re-run forward passes with gradients enabled
  3. Backward: Compute gradients using cached features as negatives
  4. Step: Update optimizer
References:

Mixed Precision Training

Mixed precision training uses lower precision (float16 or bfloat16) for most computations while maintaining float32 for critical operations.

Automatic Mixed Precision (AMP)

Benefits:
  • 🚀 Speed: 2-3× faster training on modern GPUs (A100, H100)
  • 💾 Memory: ~50% reduction in activation memory
  • 📊 Accuracy: Negligible impact with automatic loss scaling

Precision Options

Hardware Support

NVIDIA GPUs:
  • Volta (V100): FP16 via --precision amp
  • Ampere (A100): FP16 or BF16 via --precision amp or --precision amp_bf16
  • Hopper (H100): BF16 recommended via --precision amp_bf16
AMD GPUs:
  • MI250X: FP16 via --precision amp

Example: Mixed Precision Training

Avoid using --precision fp16 (pure FP16) without automatic loss scaling. Use --precision amp instead, which handles loss scaling automatically.

Patch Dropout for Vision Transformers

Patch dropout randomly drops image patches during training, leading to 2-3× speedup for Vision Transformer models without accuracy loss.

Research Background

Li et al. 2022 showed that dropping 50-75% of visual tokens during training:
  • ✅ Speeds up training by 2-3×
  • ✅ Maintains final accuracy
  • ✅ Acts as a form of data augmentation

Usage

Set patch dropout in your model config or via command-line:

Fine-tuning Without Patch Dropout

The paper recommends fine-tuning without patch dropout at the end:
Patch dropout only applies to Vision Transformer models. It has no effect on ResNet or ConvNext models.

Gradient Checkpointing

Gradient checkpointing trades compute for memory by recomputing activations during the backward pass instead of storing them.
Tradeoffs:
  • Memory: 30-50% reduction in activation memory
  • Speed: ~20% slower due to recomputation
  • Batch Size: Allows larger batch sizes
When to use:
  • Training large models (ViT-L, ViT-H, ViT-bigG)
  • Out of memory errors even with mixed precision
  • Prefer larger batch sizes over speed
Example:

SyncBatchNorm

Synchronize batch normalization statistics across GPUs for models with BatchNorm layers.
When to use:
  • ResNet models with BatchNorm layers
  • Small batch sizes per GPU (<32)
Not needed for:
  • Vision Transformers (use LayerNorm)
  • Large batch sizes (>128 per GPU)

Combining Techniques

Small-Scale Training (1-4 GPUs)

Medium-Scale Training (8-32 GPUs)

Large-Scale Training (64+ GPUs)

Very Large-Scale (256-1024 GPUs)

DDP Static Graph

PyTorch 1.11+ supports static graph optimization for DistributedDataParallel:
Benefits:
  • Slightly faster gradient synchronization
  • Lower memory overhead
Requirements:
  • Model architecture doesn’t change during training
  • PyTorch >= 1.11

Torch Compile

PyTorch 2.0+ supports model compilation for faster execution:
Benefits:
  • 10-30% speedup on A100/H100 GPUs
  • Automatic kernel fusion and optimization
Considerations:
  • First epoch is slower (compilation time)
  • Requires PyTorch >= 2.0
  • May have compatibility issues with some models
If using --grad-checkpointing with --torchcompile and DDP, the DDP dynamo optimizer is automatically disabled to avoid compatibility issues.

Int8 Training (Experimental)

OpenCLIP has beta support for int8 training using bitsandbytes:
Benefits:
  • ~10% training speedup for ViT-Huge
  • Reduced memory usage
  • No accuracy loss (preliminary results)
Status: Experimental, see tutorial

Performance Monitoring

GPU Utilization

Monitor GPU usage during training:
Target: 90-100% GPU utilization If GPU utilization is low (<80%):
  1. Increase --workers (data loading parallelism)
  2. Use faster storage (NVMe SSD)
  3. Increase --batch-size if memory allows
  4. Profile data loading pipeline

Throughput Measurement

OpenCLIP logs samples/sec during training:
  • 1506/s: Global samples per second (all GPUs)
  • 376/s/gpu: Samples per second per GPU
Typical values on A100 (40GB):

Communication Overhead

For multi-node training, monitor network bandwidth:
Expect: High bandwidth during gradient synchronization (every step)

Best Practices Summary

✅ Always Use

  1. Mixed Precision: --precision amp (or amp_bf16 on A100/H100)
  2. Distributed Loss: --local-loss --gather-with-grad (for 8+ GPUs)
  3. WebDataset: For datasets >10M samples

✅ Use When Needed

  1. Gradient Checkpointing: --grad-checkpointing (for large models)
  2. Patch Dropout: --force-patch-dropout 0.5 (for ViT models)
  3. Gradient Accumulation: --accum-freq N (when other options exhausted)

✅ Optimize For Your Setup

  1. Workers: --workers 4-12 (match to CPU cores per GPU)
  2. Batch Size: Maximize per GPU (limited by memory)
  3. Save Frequency: --save-frequency 1 (or less frequent for large models)

❌ Avoid

  • Pure FP16: Use --precision amp instead
  • Small batches: <64 per GPU reduces efficiency
  • Too many workers: >16 per GPU causes overhead
  • CSV format for large datasets: Use WebDataset

Next Steps

Multi-Node Training

Scale training across multiple machines with SLURM

Configuration

Explore all training configuration options

Data Preparation

Prepare datasets for efficient distributed training

Fine-tuning

Fine-tune pretrained models with distributed techniques